package com.yourenbang.lingyun.transaction.web.service.impl.pay.klks;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.yourenbang.lingyun.constants.BizCodeMessages;
import com.yourenbang.lingyun.constants.enums.ChannelIdEnums;
import com.yourenbang.lingyun.constants.enums.PayTransactionStatusEnum;
import com.yourenbang.lingyun.constants.enums.PlatNoEnums;
import com.yourenbang.lingyun.constants.enums.PolicyEnum;
import com.yourenbang.lingyun.constants.enums.mq.MqEnum;
import com.yourenbang.lingyun.constants.enums.table.MerchantEnum;
import com.yourenbang.lingyun.constants.enums.table.PayTransactionEnum;
import com.yourenbang.lingyun.constants.enums.table.TerminalAllyLevelEnum;
import com.yourenbang.lingyun.core.exception.BizRuntimeException;
import com.yourenbang.lingyun.core.message.Result;
import com.yourenbang.lingyun.core.util.BizAssertUtils;
import com.yourenbang.lingyun.core.util.DingdingUtils;
import com.yourenbang.lingyun.core.util.KLog;
import com.yourenbang.lingyun.core.util.date.DateFormat;
import com.yourenbang.lingyun.core.util.date.LocalDateUtils;
import com.yourenbang.lingyun.core.util.redis.CacheKey;
import com.yourenbang.lingyun.core.util.redis.RedisUtils;
import com.yourenbang.lingyun.domain.*;
import com.yourenbang.lingyun.mapper.Merchant20Mapper;
import com.yourenbang.lingyun.mapper.Merchant21Mapper;
import com.yourenbang.lingyun.mapper.MerchantPledgeCashPolicyMapper;
import com.yourenbang.lingyun.transaction.config.DingdingConfig;
import com.yourenbang.lingyun.transaction.mapper.TransactionMerchantMapper;
import com.yourenbang.lingyun.transaction.mapper.TransactionPayTransactionMapper;
import com.yourenbang.lingyun.transaction.web.domain.dto.migrate.kuaishou.MigrateDTO;
import com.yourenbang.lingyun.transaction.web.domain.dto.pay.lakala.P35FeeDTO;
import com.yourenbang.lingyun.transaction.web.domain.dto.pay.lakala.P35PayDTO;
import com.yourenbang.lingyun.transaction.web.domain.po.Merchant;
import com.yourenbang.lingyun.transaction.web.service.merchant.MerchantRecommendService;
import com.yourenbang.lingyun.transaction.web.service.pay.PayActivateService;
import com.yourenbang.lingyun.transaction.web.service.pay.PayTransactionOrderService;
import com.yourenbang.lingyun.transaction.web.service.pay.klks.PayEposService;
import com.yourenbang.lingyun.transaction.web.service.pay.klks.PayP35Service;
import com.yourenbang.lingyun.transaction.web.service.yxy.YxyTradeService;
import com.yourenbang.mcenter.api.model.dto.MqSendMessage;
import com.yourenbang.mcenter.api.service.McenterMqService;
import com.yourenbang.merchant.api.model.dto.CheckActiveRewardKlksDTO;
import com.yourenbang.merchant.api.model.dto.CreateP35ReachDTO;
import com.yourenbang.merchant.api.model.dto.CreateRewardDTO;
import com.yourenbang.merchant.api.service.MerchantRewardApiService;
import com.yourenbang.merchant.api.service.klks.MerchantReachApiService;
import com.yourenbang.merchant.api.service.yxy.MerchantYxyRewardApiService;
import com.yourenbang.terminal.api.model.dto.*;
import com.yourenbang.terminal.api.service.RpcTerminalService;
import com.yourenbang.terminal.api.service.RpcYxyTerminalService;
import com.yourenbang.transaction.api.model.vo.pay.PayTransaction;
import com.yourenbang.ucenter.api.service.AllyProfitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service("payP35Service")
public class PayP35ServiceImpl implements PayP35Service {

    private static Interner<String> weakInterner = Interners.newWeakInterner();

    @Autowired
    private McenterMqService mcenterMqService;
    @Autowired
    private MerchantPledgeCashPolicyMapper merchantPledgeCashPolicyMapper;
    @Autowired
    private Merchant21Mapper merchant21Mapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private TransactionMerchantMapper transactionMerchantMapper;
    @Autowired
    private Merchant20Mapper merchant20Mapper;
    @Autowired
    private PayTransactionOrderService payTransactionOrderService;
    @Autowired
    private RpcTerminalService rpcTerminalService;
    @Autowired
    private MerchantRecommendService merchantRecommendService;
    @Autowired
    private PayActivateService payActivateService;
    @Autowired
    private MerchantReachApiService merchantReachApiService;
    @Autowired
    private MerchantYxyRewardApiService merchantYxyRewardApiService;
    @Autowired
    private PayEposService payEposService;
    @Autowired
    private RpcTerminalService terminalService;
    @Autowired
    private RpcYxyTerminalService yxyTerminalService;
    @Autowired
    private YxyTradeService yxyTradeService;
    @Autowired
    private DingdingConfig dingdingConfig;
    @Autowired
    private MerchantRewardApiService merchantRewardApiService;
    @Autowired
    private AllyProfitService allyProfitService;
    @Autowired
    private TransactionPayTransactionMapper transactionPayTransactionMapper;
    /**
     * 用来临时存储推送消息，方便将原消息推送给合拓联盟
     */
    private static final ThreadLocal<MigrateDTO> transactionThreadLocal = new ThreadLocal<>();
    /**
     * 通知
     */
    @Override
    public void notice(MigrateDTO migrateDTO) {
        try {
            transactionThreadLocal.set(migrateDTO);
            if (StringUtils.equals(migrateDTO.getOpt(), MigrateDTO.OPT_TRANSACTION)) {
                payNotice(migrateDTO.getData());
            } else if (StringUtils.equals(migrateDTO.getOpt(), MigrateDTO.OPT_FEE)) {
                feeNotice(migrateDTO.getData());
            }
        } finally {
            transactionThreadLocal.remove();
        }
    }

    /**
     * 交易通知
     */
    private void payNotice(String param) {
        KLog.info("【P35支付通知】入参:{}", param);
        P35PayDTO p35PayDTO = JSON.parseObject(param, P35PayDTO.class);
        String lockKey = "payP35Notice" + p35PayDTO.getTransactionNo();
        try {
            //系统参考号加锁
            if (redisUtils.getLock(lockKey)) {
                payNoticeDeal(p35PayDTO);
            }
        } catch (BizRuntimeException e) {
            KLog.warn("【P35支付通知】业务异常:{}, 入参:{}", e.getErrorMessage(), param);
        } catch (Exception e) {
            KLog.error("【P35支付通知】异常:{}, 入参:{}", e.getMessage(), param, e);
        } finally {
            redisUtils.releaseLock(lockKey);
        }
    }

    /**
     * P35支付通知处理
     */
    private void payNoticeDeal(P35PayDTO p35PayDTO) {
        if (StringUtils.equals(p35PayDTO.getTransType(), "012466")) {
            KLog.warn("【P35支付通知】无效的消息,解密后的参数:{}", p35PayDTO.toJSON());
            return;
        }
        Merchant21Example merchant21Example = new Merchant21Example();
        merchant21Example.createCriteria().andMerchantNoEqualTo(p35PayDTO.getMerchantNo());
        List<Merchant21> merchant21List = merchant21Mapper.selectByExample(merchant21Example);
        Short platNo = PlatNoEnums.YXY.getCode();
        if (CollectionUtils.isEmpty(merchant21List)){
            platNo = PlatNoEnums.KLKS.getCode();
        }
        Merchant payMerchant = transactionMerchantMapper.selectByMerchantNo(p35PayDTO.getMerchantNo(), platNo);
        if(Objects.isNull(payMerchant)){ //合拓
            KLog.warn("【P35支付通知】推送给合拓的消息:{}", p35PayDTO.toJSON());
            if(Objects.isNull(transactionThreadLocal.get())){
                KLog.error("【P35支付通知】推送给合拓的消息异常:{}", p35PayDTO.toJSON());
            }else{
                MqSendMessage mqSendMessage = new MqSendMessage();
                mqSendMessage.setTopic(MqEnum.MqTopicEnum.topic_trade_lakala);
                mqSendMessage.setTag(MqEnum.MqTagEnum.tag_trade_lakala);
                mqSendMessage.setSendMsg(transactionThreadLocal.get().toJSON());
                mqSendMessage.setMessageKey(p35PayDTO.getTransactionNo());
                mcenterMqService.hetuoSend(mqSendMessage);
            }
            return;
        }
        //更正channelId 兼容40商户激活50机器 在缴纳押金的时候修改
        if (PlatNoEnums.YXY.isEquals(platNo) && StringUtils.equals(p35PayDTO.getTransType(), "412001")) {
            Terminal21 terminal21 = yxyTerminalService.getTerminalBySn(p35PayDTO.getSn());
            if (Objects.nonNull(terminal21) && !payMerchant.getChannelId().equals(terminal21.getChannelId())) {
                KLog.info("拉卡拉商户更正机具channelId 兼容40商户激活50机器 {}，{}", payMerchant, terminal21);
                yxyTerminalService.changeTerminalPolicySeries(terminal21.getTerminalId(), ChannelIdEnums.isYxy40Product(payMerchant.getChannelId()) ?
                        PolicyEnum.PolicySeries.SERIES_40.getCode() : PolicyEnum.PolicySeries.SERIES_50.getCode());
            }
        }
        PayTransaction payTransaction = createP35Order(payMerchant, p35PayDTO);
        payTransactionDeal(payMerchant,payTransaction);

        //记录机具盟友的置顶等级
        if (PlatNoEnums.YXY.isEquals(platNo)) {
            Integer transactionId = transactionPayTransactionMapper.existTransactionByMerchantAndTerminalSn(KlksPayConfig.getTransTableIndex(merchant21List.get(0).getUserBaseId()),
                    payTransaction.getMerchantNo(), payTransaction.getSn());
            if (Objects.nonNull(transactionId)) {
                KLog.info("记录机具盟友的置顶等级,{},{}", payTransaction.getSn(), merchant21List.get(0).getUserBaseId());
                allyProfitService.saveSuperiorAllyTerminalLevelFor50(payTransaction.getSn(), payTransaction.getMerchantNo(), merchant21List.get(0).getUserBaseId(),
                        payTransaction.getChannelId(), LocalDateUtils.formatByDefaultFormat(payTransaction.getTransactionTime()), TerminalAllyLevelEnum.OpTypeEnum.OP_TYPE_10.getCode());
            }
        }
    }

    /**
     * 交易处理
     */
    @Override
    public void payTransactionDeal(Merchant payMerchant,PayTransaction payTransaction) {

        //非成功订单
        if (!PayTransactionEnum.TransactionStatus.STATUS_10.isEquals(payTransaction.getStatus())) {
            return;
        }

        if (StringUtils.isNotBlank(payMerchant.getClientNo())){
            KLog.info("下游交易暂不计入分润,订单号:{},终端号:{}",payTransaction.getOrderNo(),payMerchant.getClientNo());
        }else if (MerchantEnum.CloseStatusEnum.STATUS_20.getCode().equals(payMerchant.getCloseStatus())){
            KLog.info("商户关停状态不计入分润,订单号:{},状态值:{}",payTransaction.getOrderNo(),payMerchant.getCloseStatus());
        } else {
            payEposService.profitOpt(payTransaction);
        }

        if (PlatNoEnums.KLKS.isEquals(payTransaction.getPlatNo())) {
            payNoticeKlksDeal(payTransaction, payMerchant);
        } else {
//            payNoticeYxyDeal(payTransaction, payMerchant);
        }

        //交易私信推送
        payEposService.sendTransactionLetter(payTransaction);
    }

    /**
     * 快收支付通知处理
     */
    private void payNoticeKlksDeal(PayTransaction payTransaction, Merchant payMerchant) {

        Terminal terminal;
        RpcTerminalToBindDTO toBindDTO = new RpcTerminalToBindDTO();
        toBindDTO.setSn(payTransaction.getSn());
        toBindDTO.setUserBaseId(payMerchant.getUserBaseId());
        Result<Terminal> bindResult = terminalService.bind(toBindDTO);
        if (!bindResult.isSuccess()) {

            KLog.info("【快收支付通知】调绑定机具rpc返回失败:{},payTransaction:{}", bindResult.getDesc(), payTransaction.toJSON());
            RpcTerminalBindDTO rpcTerminalBindDTO = new RpcTerminalBindDTO();
            rpcTerminalBindDTO.setBindUserBaseId(payMerchant.getUserBaseId());
            rpcTerminalBindDTO.setTerminalSn(payTransaction.getSn());

            Result<Terminal> getBindResult = rpcTerminalService.getBind(rpcTerminalBindDTO);
            if (!getBindResult.isSuccess()) {
                KLog.warn("【快收支付通知】查询绑定机具失败:{},payTransaction:{}", bindResult.getDesc(), payTransaction.toJSON());
            }
            terminal = getBindResult.getData();
        }else{
            terminal = bindResult.getData();
        }

        if (terminal == null) {
            KLog.warn("【快收支付通知】未找到机具信息,payTransaction:{},", payTransaction.toJSON());
            return;
        }


        if (ChannelIdEnums.p35.getCode().equals(terminal.getChannelId())){
            //更新通道商户信息
            updateMerchant(payMerchant, terminal, payTransaction.getTransactionTime());
            //更新P35商户标识
            merchantRecommendService.updateP35MerFlag(payTransaction.getUserBaseId(),payTransaction.getChannelId());
        }

        //押金交易
        if (StringUtils.equals(payTransaction.getTransType(), "412001")) {
            //押金记录
            p35PledgeCash(payMerchant, payTransaction);

            //创建商户达标数据
            CreateP35ReachDTO p35ReachDTO = new CreateP35ReachDTO();
            p35ReachDTO.setUserBaseId(payMerchant.getUserBaseId());
            if(ChannelIdEnums.p35.getCode().equals(terminal.getChannelId())){
                merchantReachApiService.createP35Reach(p35ReachDTO);
            }

            //初始化激活返现
            if (ChannelIdEnums.p35.getCode().equals(terminal.getChannelId())){
                addEposMerBounty(payMerchant, terminal);
            }else{
                CreateRewardDTO createRewardDTO = new CreateRewardDTO();
                createRewardDTO.setPlatNo(payMerchant.getPlatNo());
                createRewardDTO.setChannelId(payMerchant.getChannelId());
                createRewardDTO.setFromUserBaseId(payMerchant.getUserBaseId());
                createRewardDTO.setTerminalSn(terminal.getTerminalSn());
                createRewardDTO.setActiveTime(payTransaction.getTransactionTime());
                merchantRewardApiService.createReward(createRewardDTO);
            }
            //极光推送
            payEposService.merOpenJpush(payMerchant.getUserBaseId(), payMerchant.getPlatNo());
        }

        //检测激活返现
        CheckActiveRewardKlksDTO checkActiveRewardKlksDTO = new CheckActiveRewardKlksDTO();
        checkActiveRewardKlksDTO.setChannelId(payMerchant.getChannelId());
        checkActiveRewardKlksDTO.setPlatNo(payMerchant.getPlatNo());
        checkActiveRewardKlksDTO.setUserBaseId(payMerchant.getUserBaseId());
        checkActiveRewardKlksDTO.setTradeAmount(payTransaction.getTransactionAmount());
        checkActiveRewardKlksDTO.setTradeTime(payTransaction.getTransactionTime());
        merchantRewardApiService.checkRewardKlks(checkActiveRewardKlksDTO);
    }

    /**
     * 激活返现
     */
    private void addEposMerBounty(Merchant payMerchant, Terminal epos) {
        if (epos == null) {
            KLog.warn("【快收激活返现】机具信息空, payMerchant:{}", payMerchant.toJSON());
            return;
        }

        if (payMerchant.getBountyFlag() != 0) {
            return;
        }

        //激活返现关系
        payActivateService.addEposMerBounty(payMerchant.getUserBaseId(), epos.getChannelId(), epos.getTerminalSn());
        try {
            payActivateService.eposMerBounty(payMerchant, epos);
        } catch (Exception e) {
            KLog.error("【快收激活返现】异常:{}, payMerchant:{}", e.getMessage(), payMerchant.toJSON(), e);
        }
    }

    private void p35PledgeCash(Merchant merchant, PayTransaction payTransaction) {
        Merchant upMer = new Merchant(merchant.getPlatNo());
        upMer.setMerchantId(merchant.getMerchantId());
        upMer.setPledgeCash(payTransaction.getTransactionAmount());
        upMer.setPledgeCashReturn(payTransaction.getTransactionAmount());
        upMer.setPledgeCashPayType(new Short("100"));
        upMer.setPledgeCashOrderNo(payTransaction.getOrderNo());
        upMer.setPledgeCashSerialNo(payTransaction.getOrderNo());
        upMer.setPledgeCashPayGetway(ChannelIdEnums.getChannelIdEnums(payTransaction.getChannelId()).getMsg());
        upMer.setPledgeCashStatus(MerchantEnum.PledgeCashStatusEnum.STATUS_200.getCode());
        upMer.setPledgeCashSuccessTime(payTransaction.getTransactionTime());
        upMer.setMerchantPledgeCashPolicyId(0);
        int upMerCc = transactionMerchantMapper.updateByPrimaryKeySelective(upMer);
        BizAssertUtils.assertOne(upMerCc, "更新商户失败");
    }

    private void p35PledgeCashUnPay(Merchant merchant, PayTransaction payTransaction) {
        Merchant upMer = new Merchant(merchant.getPlatNo());
        upMer.setMerchantId(merchant.getMerchantId());
        upMer.setPledgeCash(payTransaction.getTransactionAmount());
        upMer.setPledgeCashReturn(payTransaction.getTransactionAmount());
        upMer.setPledgeCashPayType(new Short("100"));
        upMer.setPledgeCashOrderNo(payTransaction.getOrderNo());
        upMer.setPledgeCashSerialNo(payTransaction.getOrderNo());
        upMer.setPledgeCashPayGetway(ChannelIdEnums.getChannelIdEnums(payTransaction.getChannelId()).getMsg());
        upMer.setPledgeCashStatus(MerchantEnum.PledgeCashStatusEnum.STATUS_200.getCode());
        upMer.setPledgeCashSuccessTime(payTransaction.getTransactionTime());
        upMer.setMerchantPledgeCashPolicyId(0);
        int upMerCc = transactionMerchantMapper.updateByPrimaryKeySelective(upMer);
        BizAssertUtils.assertOne(upMerCc, "更新商户失败");
    }

    /**
     * 更新商户考核开始时间
     */
    private void updateMerchant(Merchant merchant, Terminal epos, LocalDateTime transTime) {
        if (merchant.getTerminalActiveTime() != null) {
            return;
        }

        RpcTerminalRateDTO rpcTerminalRateDTO = new RpcTerminalRateDTO();
        rpcTerminalRateDTO.setTerminalRateId(epos.getTerminalRateId());
        TerminalRate eposRate = rpcTerminalService.getRate(rpcTerminalRateDTO).getData();
        if (eposRate == null) {
            return;
        }
        Merchant20 upMer = new Merchant20();
        upMer.setMerchantId(merchant.getMerchantId());
        upMer.setTerminalActiveTime(transTime);

        if (merchant.getDiscountsRateBeginTime() == null) {
            upMer.setDiscountsRateBeginTime(LocalDateUtils.localDateToLocalDateTime(upMer.getTerminalActiveTime().toLocalDate()));
            upMer.setDiscountsRateEndTime(LocalDateUtils.localDateToLocalDateTime(upMer.getTerminalActiveTime().plusDays(eposRate.getTerminalRateDiscountDay()).toLocalDate()));
            upMer.setDiscountsRatePastFlag("0");
        }
        int updateCount = merchant20Mapper.updateByPrimaryKeySelective(upMer);
        BizAssertUtils.assertOne(updateCount, "更新通道商户失败");

        merchant.setTerminalActiveTime(transTime);
    }

    /**
     * 创建P35订单
     */
    private PayTransaction createP35Order(Merchant merchant, P35PayDTO p35PayDTO) {
        if (merchant == null) {
            KLog.warn("【P35支付通知】未找到商户,解密后的参数:{}", p35PayDTO.toJSON());
            String msg = "【P35交易回调】未找到商户\n" +
                    "交易回调参数:" + p35PayDTO.toJSON() + "\n" +
                    "请尽快处理";
            DingdingUtils.sendToDingding(msg, dingdingConfig.getDingdingOperatingToken());
            throw new BizRuntimeException(BizCodeMessages.UNKNOWN_ERROR, "未找到商户");
        }

        PayTransaction po = new PayTransaction();
        po.setOrderNo(p35PayDTO.getTransactionNo());
        po.setTransactionNo(p35PayDTO.getTransactionNo());
        po.setUserBaseId(merchant.getUserBaseId());
        po.setMerchantId(merchant.getMerchantId());
        po.setMerchantNo(p35PayDTO.getMerchantNo());
        po.setMerchantName(merchant.getMerchantName());
        po.setPhone(merchant.getPhone());
        po.setRealName(merchant.getRealName());
        po.setRate(KlksPayConfig.fmtRate(p35PayDTO.getCrdflg(), merchant.getRateCredit()).getShotCode());
        po.setTransactionAmount(new BigDecimal(p35PayDTO.getTransAmt()).divide(new BigDecimal("100")));
        po.setTransactionFee(StringUtils.isNotBlank(p35PayDTO.getTransFee()) ? new BigDecimal(p35PayDTO.getTransFee()) : getFeeByCache(p35PayDTO.getTransactionNo()));
        po.setCardFlag(KlksPayConfig.fmtCrdFlg(p35PayDTO.getCrdflg()));
        po.setTerminalId(p35PayDTO.getTermId());        //终端号
        po.setSn(p35PayDTO.getSn());         //机具号
        po.setTransactionCardNo(p35PayDTO.getCardNo());
        po.setSettlementCardNo(merchant.getBankCard());
        po.setSettlementBank(merchant.getOpenBank());
        po.setStatus(StringUtils.equals(p35PayDTO.getTransStatus(), "S") ? PayTransactionStatusEnum.STATUS_10.getCode() : PayTransactionStatusEnum.STATUS_20.getCode());
        po.setTransactionTime(DateFormat.DATETIME_COMPACT.parse(p35PayDTO.getTransTime()));
        po.setSysRef(p35PayDTO.getSrefNo());
        po.setTransType(p35PayDTO.getTransType());
        po.setPlatNo(merchant.getPlatNo());
        po.setChannelId(merchant.getChannelId());
        po.setProfitFlag(KlksPayConfig.getProfitFlag(po));
        if (MerchantEnum.CloseStatusEnum.STATUS_20.getCode().equals(merchant.getCloseStatus())) {
            po.setProfitFlag(false);
        }
        po.setClientNo(merchant.getClientNo());

        //存在系统参考号,不插入
        PayTransaction oldPay = payTransactionOrderService.getByOrderNo(merchant.getUserBaseId(), p35PayDTO.getTransactionNo());

        if (oldPay == null) {
            po.setVersion(0);
            po.setCreateTime(LocalDateTime.now());
            po.setTransactionDay(DateFormat.DATE_COMPACT.format(po.getTransactionTime()));
            po.setTransactionMonth(DateFormat.DATE_MONTH.format(po.getTransactionTime()));
            payTransactionOrderService.insert(po);
            KLog.info("【P35支付通知】插入交易流水:{},解密后的参数:{}", po.toJSON(), p35PayDTO.toJSON());
            return po;
        } else {
            //原状态成功
            if (PayTransactionStatusEnum.STATUS_10.isEquals(oldPay.getStatus())) {
                KLog.info("【P35支付通知】原交易已成功,无需处理,解密后的参数:{}", p35PayDTO.toJSON());
                return oldPay;
            }
            PayTransaction uppo = new PayTransaction();
            BeanUtils.copyProperties(po, uppo);
            uppo.setPayTransactionId(oldPay.getPayTransactionId());
            uppo.setVersion(oldPay.getVersion());
            uppo.setUpdateTime(LocalDateTime.now());
            payTransactionOrderService.updateById(uppo);

            KLog.info("【P35支付通知】更新交易流水:{},解密后的参数:{}", uppo.toJSON(), p35PayDTO.toJSON());
            return uppo;
        }

    }

    //从缓存中尝试获取手续费
    private BigDecimal getFeeByCache(String transactionNo) {
        BigDecimal fee = redisUtils.get(getFeeNoticeCacheKey(transactionNo), BigDecimal.class);
        if (fee == null) {
            return BigDecimal.ZERO;
        }
        return fee;
    }

    private CacheKey getFeeNoticeCacheKey(String transactionNo) {
        return new CacheKey(CacheKey.CacheKeyPrefix2.pay,
                StringUtils.join(new String[]{"payEposFeeNotice", transactionNo}, ":"));
    }

    /**
     * 手续费通知
     */
    private void feeNotice(String param) {
        KLog.info("【P35手续费通知】入参:{}", param);

        //解析json
        P35FeeDTO feeDTO = JSON.parseObject(param, P35FeeDTO.class);

        PayTransaction oldPay = payTransactionOrderService.getByOrderNo(feeDTO.getTransactionNo());

        if (oldPay == null) {
            KLog.warn("【P35手续费通知】未找到交易,缓存费率信息,解密后的参数:{}", param);
            redisUtils.set(getFeeNoticeCacheKey(feeDTO.getTransactionNo()), feeDTO.getTransFee(), 60 * 30);
            //有可能是合拓联盟的，推送给合拓
            KLog.warn("【P35手续费通知】有可能是合拓联盟的,推送给合拓的消息:{}", param);
            if(Objects.isNull(transactionThreadLocal.get())){
                KLog.error("【P35手续费通知】有可能是合拓联盟的,推送给合拓的消息异常:{}", param);
            }else{
                MqSendMessage mqSendMessage = new MqSendMessage();
                mqSendMessage.setTopic(MqEnum.MqTopicEnum.topic_trade_lakala);
                mqSendMessage.setTag(MqEnum.MqTagEnum.tag_trade_lakala);
                mqSendMessage.setSendMsg(transactionThreadLocal.get().toJSON());
                mqSendMessage.setMessageKey(feeDTO.getTransactionNo());
                mcenterMqService.hetuoSend(mqSendMessage);
            }
            return;
        }
        if (oldPay.getTransactionFee() != null
                && oldPay.getTransactionFee().compareTo(BigDecimal.ZERO) != 0) {
            KLog.info("【P35手续费通知】已更新手续费信息,解密后的参数:{}", param);
            return;
        }

        PayTransaction upPay = new PayTransaction();
        upPay.setPayTransactionId(oldPay.getPayTransactionId());
        upPay.setVersion(oldPay.getVersion());
        upPay.setUserBaseId(oldPay.getUserBaseId());
        upPay.setUpdateTime(LocalDateTime.now());
        upPay.setOrderNo(feeDTO.getTransactionNo());
        upPay.setTransactionNo(feeDTO.getTransactionNo());
        upPay.setTransactionFee(new BigDecimal(feeDTO.getTransFee()));
        payTransactionOrderService.updateById(upPay);

        KLog.info("【P35手续费通知】更新交易流水:{},解密后的参数:{}", upPay.toJSON(), param);

    }
}
